package de.e2it3t.schulverwaltung.ui;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import de.e2it3t.schulverwaltung.App;
import de.e2it3t.schulverwaltung.data.CommonTableModel;
import de.e2it3t.schulverwaltung.data.TimeHelper;
import de.e2it3t.schulverwaltung.data.Klasse;
import de.e2it3t.schulverwaltung.data.LehreinheitTable;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * Ansicht der Lehreinheiten. <br>
 * <br>
 * Die View zeigt eine Liste mit allen Lehreinheiten für eine Klasse und bietet
 * die Möglichkeit Lehreinheiten hinzuzufügen, zu löschen und zu bearbeiten.
 * Eine Combobox entscheidet für welche Klasse die Lehreinheiten aufgelistet und
 * hinzugefügt werden.<br>
 * <br>
 * Tip: Die Liste erlaubt eine Selektierung mehrerer Lehreinheiten mit STRG
 * und / oder Shift.
 * 
 * @author Viktor Reiser
 */
public class LehreinheitView extends JPanel implements AppView {

    private JTable lehreinheitenTable;
    private JButton deleteButton;
    private JButton addButton;
    private JButton editButton;
    private JComboBox klasseComboBox;
    
    private List<LehreinheitTable> lehreinheitenData;
    
    
    public LehreinheitView() {
        setupLehreinheitenTable();
        setupDeleteButton();
        setupEditButton();
        setupAddButton();
        setupKlasseComboBox();
        
        setLayout(new FormLayout(
                "pref, 5px, fill:pref:grow, 5px, pref, 5px, pref, 5px, pref, 5px, pref",
                "pref, 5px, fill:pref:grow"));
        CellConstraints cc = new CellConstraints();
        
        add(new JLabel("Klasse: "), cc.xy(1, 1));
        add(klasseComboBox, cc.xy(3, 1));
        add(addButton, cc.xy(5, 1));
        add(editButton, cc.xy(7, 1));
        add(deleteButton, cc.xy(9, 1));
        add(App.createInfoButton("<html>Die Stundenplanansicht listet alle Lehreinheiten einer Klasse "
                + "für eine Woche. Man kann Lehreinheiten hinzufügen, bearbeiten und löschen.<br><br>"
                + "Eine Lehreinheit wird in einem Zeitraum (Uhrzeit Beginn und Ende) von einem Lehrer "
                + "für die gewählte Klassen in einem Fach und einem Raum und einem Wochentag gehalten.<br><br>"
                + "Die Validierung sieht nicht vor, dass die gewählte Räumlichkeit oder der gewählte Lehrer bereits von "
                + "einer anderen Klasse belegt sind (d.h. Lehrblöcke bleiben unbeachtet). Weiterhin sind die "
                + "Räume, Lehrer und die von diesen unterrichteten Fächer fest in der Datenbank hinterlegt.", 500, 220), cc.xy(11, 1));
        add(new JScrollPane(lehreinheitenTable), cc.xywh(1, 3, 11, 1));
    }
    
    private void setupLehreinheitenTable() {
        lehreinheitenTable = new JTable();
        // Liste soll den kompletten, zur Verfügung stehenden Platz nutzen
        lehreinheitenTable.setFillsViewportHeight(true);
        // Hack: wir brauchen eine gewünschte Größe, damit die Liste
        // gescrollt werden kann, wenn sie zu viele Einträge hat
        lehreinheitenTable.setPreferredScrollableViewportSize(new Dimension(50, 50));
        // wir wollen die Liste durch Klick auf die Header sortieren können
        lehreinheitenTable.setAutoCreateRowSorter(true);
        lehreinheitenTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // Buttons ensprechend der Selektion de-/aktivieren
                deleteButton.setEnabled(
                        lehreinheitenTable.getSelectedRowCount() != 0);
                editButton.setEnabled(
                        lehreinheitenTable.getSelectedRowCount() == 1);
                
                // Doppelklick
                if (e.getClickCount() == 2) {
                    editSelectedLehreinheit();
                }
            }
        });
    }
    
    private void setupDeleteButton() {
        deleteButton = new JButton("Löschen");
        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                deleteSelectedLehreinheit();
            }
        });
    }
    
    private void setupAddButton() {
        addButton = new JButton("Hinzufügen");
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                // neue Lehreinheit
                new LehreinheitDialog(
                        LehreinheitView.this,
                        ((Klasse) klasseComboBox.getSelectedItem()).getId()
                ).setVisible(true);
            }
        });
    }
    
    private void setupEditButton() {
        editButton = new JButton("Bearbeiten");
        editButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                editSelectedLehreinheit();
            }
        });
    }
    
    private void setupKlasseComboBox() {
        klasseComboBox = new JComboBox();
        klasseComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                loadView();
            }
        });
    }
    
    
    /**
     * Erneuern der View für die gewählte Klasse.
     */
    private void loadView() {
        if (klasseComboBox.getItemCount() == 0) {
            // keine Klassen, keine Lehreinheiten
            lehreinheitenData = new ArrayList<LehreinheitTable>();
        } else {
            // lade Lehreinheiten für die selektierte Klasse
            lehreinheitenData = App.getDatabase().getLehreinheitenTable(
                    ((Klasse)klasseComboBox.getSelectedItem()).getId());
        }
        
        addButton.setEnabled(false);
        
        if (klasseComboBox.getItemCount() == 0) {
            addButton.setToolTipText("Keine Klassen vorhanden");
        } else if (!App.getDatabase().hasRaeume()){
            addButton.setToolTipText("Keine Räume vorhanden");
        } else  if (!App.getDatabase().hasFaecherMitLehrern()) {
            addButton.setToolTipText("Keine unterrichteten Fächer vorhanden");
        } else {
            addButton.setEnabled(true);
            addButton.setToolTipText(null);
        }
        
        // Lade die Liste mit Lehreinheiten
        lehreinheitenTable.setModel(new CommonTableModel(
                lehreinheitenData,
                new String[] {
                    "tag", "uhrzeitBeginn", "uhrzeitEnde", "fach", "lehrer", "raum"
                },
                new String[] {
                    "Tag", "Von", "Bis", "Fach", "Lehrer", "Raum"
                }));
        
        // sortiere Liste nach der ersten Spalte, Wochentag
        lehreinheitenTable.getRowSorter().toggleSortOrder(0);
        // für den Wochentag müssen brauchen wir einen speziellen Renderer,
        // welcher eine Zahl in einen sprechenden Namen umwandelt
        lehreinheitenTable.getColumnModel().getColumn(0).setCellRenderer(
                new TagCellRenderer());
        // Renderer für Zeiten
        lehreinheitenTable.getColumnModel().getColumn(1).setCellRenderer(
                new TimeCellRenderer());
        lehreinheitenTable.getColumnModel().getColumn(2).setCellRenderer(
                new TimeCellRenderer());
    }
    
    /**
     * Selektierte Lehreinheit bearbeiten (wenn genau eine selektiert ist).
     */
    private void editSelectedLehreinheit() {
        if (lehreinheitenTable.getSelectedRowCount() != 1) {
            return;
        }
        
        int lehreinheitId = lehreinheitenData.get(
                lehreinheitenTable.convertRowIndexToModel(
                lehreinheitenTable.getSelectedRow())).getId();

        new LehreinheitDialog(this, 0, lehreinheitId).setVisible(true);
    }
    
    /**
     * Selektierte Lehreinheiten löschen (wenn welche selektiert sind). <br>
     * <br>
     * Es wird nachgefragt, ob wirklich gelöscht werden soll.
     */
    private void deleteSelectedLehreinheit() {
        if (lehreinheitenTable.getSelectedRowCount() == 0) {
            return;
        }
        
        int schuelerCount = lehreinheitenTable.getSelectedRowCount();
        int result = JOptionPane.showConfirmDialog(
                null,
                "Wollen sie wirklich "
                + (schuelerCount == 1 ? "den gewählten" : schuelerCount + "")
                + " Schüler löschen?",
                "Schüler löschen?",
                JOptionPane.YES_NO_OPTION, 
                JOptionPane.QUESTION_MESSAGE);

        if (result == JOptionPane.YES_OPTION) {
            for (int index : lehreinheitenTable.getSelectedRows()) {
                App.getDatabase().deleteLehreinheit(lehreinheitenData.get(
                        lehreinheitenTable.convertRowIndexToModel(index)).getId());
            }
            
            loadView();
        }
    }
    
    
    @Override
    public void refreshView() {
        editButton.setEnabled(false);
        deleteButton.setEnabled(false);
        
        // lade alle vorhandenen Klassen in die Combobox
        klasseComboBox.removeAllItems();
        
        for (Klasse klasse : App.getDatabase().getKlassen()) {
            klasseComboBox.addItem(klasse);
        }
        
        loadView();
    }

    @Override
    public JComponent getView() {
        return this;
    }

    @Override
    public String getViewName() {
        return "Stundenplan";
    }
    
    
    /**
     * Helfer, welcher Wochentage in einer JTable rendert.
     */
    private static class TagCellRenderer extends DefaultTableCellRenderer {
        
        @Override
        public void setValue(Object value) {
            if (value == null || !(value instanceof Integer)) {
                super.setValue(value);
                return;
            }
            
            setText(TimeHelper.getDayString((Integer)value));
        }
    }
    
    private static class TimeCellRenderer extends DefaultTableCellRenderer {
        
        @Override
        public void setValue(Object value) {
            if (value == null || !(value instanceof Time)) {
                super.setValue(value);
                return;
            }
            
            setText(TimeHelper.getTimeString((Time)value));
        }
    }
}
